// import com.alibaba.druid.sql.SQLUtils;
// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
// import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
// import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
// import com.alibaba.druid.sql.ast.statement.SQLTableSource;
// import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

#include "OracleSelectJoin.h"
#include "../../../../SQLUtils.h"
#include "../../../../ast/SQLExpr.h"
#include "../../../../ast/expr/SQLIdentifierExpr.h"
#include "../../../../ast/statement/SQLExprTableSource.h"
#include "../../../../ast/statement/SQLTableSource.h"
#include "../../visitor/OracleASTVisitor.h"
#include "../../../../visitor/SQLASTVisitor.h"
#include "../../../../../utils/instanceof.h"
#include "../../../../../utils/listTran.h"
#include "OracleSelectTableReference.h"

OracleSelectJoin::OracleSelectJoin(string_ptr alias)
    : SQLJoinTableSource(alias)
{
}

OracleSelectJoin::OracleSelectJoin()
{
}

OracleSelectJoin::OracleSelectJoin(SQLTableSource_ptr left, SQLJoinTableSource_JoinType_ptr joinType, SQLTableSource_ptr right, SQLExpr_ptr condition)
    : SQLJoinTableSource(left, joinType, right, condition)
{
}

// @Override
void OracleSelectJoin::accept0(SQLASTVisitor_ptr visitor)
{
  if (instanceof <SQLASTVisitor, OracleASTVisitor>(visitor))
  {
    this->accept0(std::dynamic_pointer_cast<OracleASTVisitor>(visitor));
  }
  else
  {
    SQLJoinTableSource::accept0(visitor);
  }
}

void OracleSelectJoin::accept0(OracleASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(OracleSelectJoin)))
  {
    acceptChild(visitor, this->left);
    acceptChild(visitor, this->right);
    acceptChild(visitor, this->condition);
    SQLObject_list_ptr tmp1 = ListTran::tran_class<SQLExpr, SQLObject>(this->using_list);
    acceptChild(visitor, tmp1);
    acceptChild(visitor, this->flashback);
  }

  visitor->endVisit(SharedObject(OracleSelectJoin));
}

// @Override
bool OracleSelectJoin::equals(Object_ptr o)
{
  if (this == o.get())
  {
    return true;
  }
  if (o == nullptr || getClass() != o->getClass())
  {
    return false;
  }
  if (!SQLJoinTableSource::equals(o))
  {
    return false;
  }

  OracleSelectJoin_ptr that = std::dynamic_pointer_cast<OracleSelectJoin>(o);

  if (pivot != nullptr ? !pivot->equals(that->pivot) : that->pivot != nullptr)
  {
    return false;
  }
  if (unpivot != nullptr ? !unpivot->equals(that->unpivot) : that->unpivot != nullptr)
  {
    return false;
  }
  return flashback != nullptr ? flashback->equals(that->flashback) : that->flashback == nullptr;
}

// @Override
int OracleSelectJoin::hashCode()
{
  int result = pivot != nullptr ? pivot->hashCode() : 0;
  result = 31 * result + (unpivot != nullptr ? unpivot->hashCode() : 0);
  result = 31 * result + (flashback != nullptr ? flashback->hashCode() : 0);
  return result;
}

string_ptr OracleSelectJoin::toString()
{
  return SQLUtils::toOracleString(SharedObject(OracleSelectJoin));
}

SQLObject_ptr OracleSelectJoin::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<OracleSelectJoin>(new OracleSelectJoin());
  std::shared_ptr<OracleSelectJoin> x = std::dynamic_pointer_cast<OracleSelectJoin>(clone_tmp);
  // OracleSelectJoin x = new OracleSelectJoin();
  cloneTo(x);

  if (pivot != nullptr)
  {
    x->setPivot(std::dynamic_pointer_cast<SQLPivot>(pivot->clone()));
  }

  if (unpivot != nullptr)
  {
    x->setUnpivot(std::dynamic_pointer_cast<SQLUnpivot>(unpivot->clone()));
  }

  if (flashback != nullptr)
  {
    x->setFlashback(std::dynamic_pointer_cast<SQLExpr>(flashback->clone()));
  }

  return x;
}

void OracleSelectJoin::setLeft(string_ptr tableName)
{
  SQLExprTableSource_ptr tableSource;
  if (tableName == nullptr || tableName->length() == 0)
  {
    tableSource = nullptr;
  }
  else
  {
    tableSource = OracleSelectTableReference_ptr(new OracleSelectTableReference(SQLIdentifierExpr_ptr(new SQLIdentifierExpr(tableName))));
  }
  this->SQLJoinTableSource::setLeft(tableSource);
}

void OracleSelectJoin::setRight(string_ptr tableName)
{
  SQLExprTableSource_ptr tableSource;
  if (tableName == nullptr || tableName->length() == 0)
  {
    tableSource = nullptr;
  }
  else
  {
    tableSource = OracleSelectTableReference_ptr(new OracleSelectTableReference(SQLIdentifierExpr_ptr(new SQLIdentifierExpr(tableName))));
  }
  this->SQLJoinTableSource::setRight(tableSource);
}

SQLJoinTableSource_ptr OracleSelectJoin::join(SQLTableSource_ptr right, SQLJoinTableSource_JoinType_ptr joinType, SQLExpr_ptr condition)
{
  SQLJoinTableSource_ptr joined = SQLJoinTableSource_ptr(new OracleSelectJoin(SharedObject(OracleSelectJoin), joinType, right, condition));
  return joined;
}
